//############################################################################
//## WiiDS Emulator (DeSmuME Port)
//##--------------------------------------------------------------------------
//## input.cpp
//## - Wii Controller Setup
//############################################################################

#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ogcsys.h>
#include <unistd.h>
#include <wiiuse/wpad.h>

//#include "wiids.h"
#include "btnmaps.h"
//#include "audio.h"
//#include "video.h"
#include "input.h"
//#include "ndssupport.h"
//#include "fastmath.h"
#include "wiiusbsupport.h"
#include "gui/gui.h"

int rumbleRequest[4] = {0,0,0,0};
GuiTrigger userInput[4];

static int rumbleCount[4] = {0,0,0,0};

static int gameRumbleCount = 0, menuRumbleCount = 0, rumbleCountAlready = 0;

static unsigned int ndspadmap[13]; // NDS Buttons
u32 btnmap[5][13]; // Button Maps

void ResetControls(int wiiCtrl)
{
	int i;

	// NDS Default Buttons
	// All unknown pads are mapped to this.
	i=0;
	ndspadmap[i++] = NDS_BUTTON_A;
	ndspadmap[i++] = NDS_BUTTON_B;
	ndspadmap[i++] = NDS_BUTTON_X;
	ndspadmap[i++] = NDS_BUTTON_Y;
	ndspadmap[i++] = NDS_UP;
	ndspadmap[i++] = NDS_RIGHT;
	ndspadmap[i++] = NDS_DOWN;
	ndspadmap[i++] = NDS_LEFT;
	ndspadmap[i++] = NDS_TRIGGER_L;
	ndspadmap[i++] = NDS_TRIGGER_R;
	ndspadmap[i++] = NDS_START;
	ndspadmap[i++] = NDS_SELECT;
	ndspadmap[i++] = NDS_TAP;

	// Gamecube Controller
//	if(wiiCtrl == CTRLR_GCPAD || wiiCtrl == -1)
//	{
//		i=0;
//		btnmap[CTRLR_GCPAD][i++] = PAD_BUTTON_???;
//	}

	// Wiimote
//	if(wiiCtrl == CTRLR_WIIMOTE || wiiCtrl == -1)
//	{
//		i=0;
//		btnmap[CTRLR_WIIMOTE][i++] = WPAD_BUTTON_???;
//	}

	// Classic Controller
	if(wiiCtrl == CTRLR_CLASSIC || wiiCtrl == -1)
	{
		i=0;
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_A;		// A
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_B;		// B
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_X;		// X
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_Y;		// Y
		btnmap[CTRLR_CLASSIC][i++] = NDS_UP;						// Up
		btnmap[CTRLR_CLASSIC][i++] = NDS_RIGHT;					// Right
		btnmap[CTRLR_CLASSIC][i++] = NDS_DOWN;						// Down
		btnmap[CTRLR_CLASSIC][i++] = NDS_LEFT;						// Left
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L;	// L Trigger
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_FULL_L;	// R Trigger
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_PLUS;		// Start
		btnmap[CTRLR_CLASSIC][i++] = WPAD_CLASSIC_BUTTON_MINUS;	// Select
		btnmap[CTRLR_CLASSIC][i++] = WPAD_BUTTON_A;				// Tap
	}

	// Wiimote + Nunchuk
	if(wiiCtrl == CTRLR_NUNCHUK || wiiCtrl == -1)
	{
		i=0;
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_RIGHT;		// A
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_DOWN;			// B
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_UP;			// X
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_LEFT;			// Y
		btnmap[CTRLR_NUNCHUK][i++] = NDS_UP;					// UP
		btnmap[CTRLR_NUNCHUK][i++] = NDS_RIGHT;				// Right
		btnmap[CTRLR_NUNCHUK][i++] = NDS_DOWN;					// Down
		btnmap[CTRLR_NUNCHUK][i++] = NDS_LEFT;					// Left
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_NUNCHUK_BUTTON_Z;	// L Trigger
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_B;			// R Trigger
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_PLUS;			// Start
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_MINUS;		// Select
		btnmap[CTRLR_NUNCHUK][i++] = WPAD_BUTTON_A;			// Tap
	}

	// Keyboard + Mouse
	if(wiiCtrl == CTRLR_KEYBOARD || wiiCtrl == -1)
	{
		i=0;
		btnmap[CTRLR_KEYBOARD][i++] = KS_Z;		// A
		btnmap[CTRLR_KEYBOARD][i++] = KS_X;		// B
		btnmap[CTRLR_KEYBOARD][i++] = KS_C;		// X
		btnmap[CTRLR_KEYBOARD][i++] = KS_V;		// Y
		btnmap[CTRLR_KEYBOARD][i++] = KS_Up;		// Up
		btnmap[CTRLR_KEYBOARD][i++] = KS_Right;	// Right
		btnmap[CTRLR_KEYBOARD][i++] = KS_Down;		// Down
		btnmap[CTRLR_KEYBOARD][i++] = KS_Left;		// Left
		btnmap[CTRLR_KEYBOARD][i++] = KS_Shift_L;	// L Trigger
		btnmap[CTRLR_KEYBOARD][i++] = KS_Shift_R;	// R Trigger
		btnmap[CTRLR_KEYBOARD][i++] = KS_Return;	// Start
		btnmap[CTRLR_KEYBOARD][i++] = KS_space;	// Select
		btnmap[CTRLR_KEYBOARD][i++] = MOUSEL;		// Tap
	}
}

/****************************************************************************
 * UpdatePads
 *
 * Scans pad and wpad
 ***************************************************************************/
void UpdatePads()
{
	WPAD_ScanPads();
	PAD_ScanPads();

	for(int i=3; i >= 0; i--)
	{
		userInput[i].pad.btns_d = PAD_ButtonsDown(i);
		userInput[i].pad.btns_u = PAD_ButtonsUp(i);
		userInput[i].pad.btns_h = PAD_ButtonsHeld(i);
		userInput[i].pad.stickX = PAD_StickX(i);
		userInput[i].pad.stickY = PAD_StickY(i);
		userInput[i].pad.substickX = PAD_SubStickX(i);
		userInput[i].pad.substickY = PAD_SubStickY(i);
		userInput[i].pad.triggerL = PAD_TriggerL(i);
		userInput[i].pad.triggerR = PAD_TriggerR(i);
	}
}

/****************************************************************************
 * SetupPads
 *
 * Sets up userInput triggers for use
 ***************************************************************************/
void SetupPads()
{
	PAD_Init();
	WPAD_Init();

	// read wiimote accelerometer and IR data
	WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR);
	WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight);

	for(int i=0; i < 4; i++)
	{
		userInput[i].chan = i;
		userInput[i].wpad = WPAD_Data(i);
	}
}

/****************************************************************************
 * ShutoffRumble
 ***************************************************************************/
void ShutoffRumble()
{
	for(int i=0;i<4;i++)
	{
		WPAD_Rumble(i, 0);
		rumbleCount[i] = 0;
		rumbleRequest[i] = 0;
	}
	PAD_ControlMotor(PAD_CHAN0, PAD_MOTOR_STOP);
}

/****************************************************************************
 * DoRumble
 ***************************************************************************/
void DoRumble(int i)
{
	if(!Settings.Rumble) return;
	if(rumbleRequest[i] && rumbleCount[i] < 3)
	{
		WPAD_Rumble(i, 1); // rumble on
		rumbleCount[i]++;
	}
	else if(rumbleRequest[i])
	{
		rumbleCount[i] = 12;
		rumbleRequest[i] = 0;
	}
	else
	{
		if(rumbleCount[i])
			rumbleCount[i]--;
		WPAD_Rumble(i, 0); // rumble off
	}
}

static int SilenceNeeded = 0;
static void updateRumble()
{
	if(!Settings.Rumble) return;

	bool r = false;
	if (ConfigRequested) r = (menuRumbleCount > 0);
	else r = (gameRumbleCount > 0) || (menuRumbleCount > 0);

	if (SilenceNeeded > 0)
	{
		if (r)
		{
			SilenceNeeded = 5;
			// It will always be greater than 0 after that!
			r = false;
		}
		else
		{
			if (--SilenceNeeded > 0) r = false;
		}
	}
	// Rumble wii remote 0
	WPAD_Rumble(0, r);
	PAD_ControlMotor(PAD_CHAN0, r?PAD_MOTOR_RUMBLE:PAD_MOTOR_STOP);
}

void updateRumbleFrame()
{
	if(!Settings.Rumble) return;
	// If we already rumbled continuously for more than 50 frames,
	// then disable rumbling for a while.
	if (rumbleCountAlready > 70) {
		SilenceNeeded = 5;
		rumbleCountAlready = 0;
	} else if (ConfigRequested) {
		if (menuRumbleCount>0) ++rumbleCountAlready;
		else rumbleCountAlready=0;
	} else {
		if (gameRumbleCount>0 || menuRumbleCount>0)
			++rumbleCountAlready;
		else rumbleCountAlready=0;
	}
	updateRumble();
	if (gameRumbleCount>0 && !ConfigRequested) --gameRumbleCount;
	if (menuRumbleCount>0) --menuRumbleCount;
}

void systemGameRumble(int RumbleForFrames) {
	if (RumbleForFrames > gameRumbleCount) gameRumbleCount = RumbleForFrames;
}

void systemGameRumbleOnlyFor(int OnlyRumbleForFrames) {
	gameRumbleCount = OnlyRumbleForFrames;
}

u32 StandardMovement(unsigned short chan)
{
	u32 J = 0;
	s8 pad_x = userInput[chan].pad.stickX;
	s8 pad_y = userInput[chan].pad.stickY;
	s8 wm_ax = userInput[0].WPAD_StickX(0);
	s8 wm_ay = userInput[0].WPAD_StickY(0);

// Gamecube Joystick Input
	// Is XY inside the "zone"?
	if (pad_x * pad_x + pad_y * pad_y > PADCAL * PADCAL)
	{
		if (pad_y == 0)
		{
			if(pad_x > 0)
			{ 
				J |= NDS_RIGHT;
			}
			else if(pad_x < 0)
			{
				J |= NDS_LEFT;
			}
		}
		if (pad_x == 0)
		{
			if(pad_y > 0)
			{
				J |= NDS_UP;
			}
			else if(pad_y < 0)
			{
				J |= NDS_DOWN;
			}
		}
		if ((pad_x|pad_y) != 0)
		{
			if ((fabs((double)(pad_y) / (double)(pad_x))) < 2.41421356237)
			{
				if (pad_x >= 0)
					J |= NDS_RIGHT;
				else
					J |= NDS_LEFT;
			}
			if ((fabs((double)(pad_x) / (double)(pad_y))) < 2.41421356237)
			{
				if (pad_y >= 0)
					J |= NDS_UP;
				else
					J |= NDS_DOWN;
			}
		}
	}

// Wii Joystick (classic, nunchuk) Input
	// Is XY inside the "zone"?
	if (wm_ax * wm_ax + wm_ay * wm_ay > PADCAL * PADCAL)
	{
		if (wm_ay == 0)
		{
			if(wm_ax > 0)
			{ 
				J |= NDS_RIGHT;
			}
			else if(wm_ax < 0)
			{
				J |= NDS_LEFT;
			}
		}
		if (wm_ax == 0)
		{
			if(wm_ay > 0)
			{
				J |= NDS_UP;
			}
			else if(wm_ay < 0)
			{
				J |= NDS_DOWN;
			}
		}
		if (wm_ax != 0 && wm_ay != 0)
		{
			if ((fabs((double)(wm_ay) / (double)(wm_ax))) < 2.41421356237)
			{
				if (wm_ax >= 0)
					J |= NDS_RIGHT;
				else
					J |= NDS_LEFT;
			}
			if ((fabs((double)(wm_ax) / (double)(wm_ay))) < 2.41421356237)
			{
				if (wm_ay >= 0)
					J |= NDS_UP;
				else
					J |= NDS_DOWN;
			}
		}
	}
	return J;
}

u32 StandardDPad(unsigned short pad)
{
	u32 J = 0;
	u32 jp = PAD_ButtonsHeld(pad);
	u32 exp_type;
	if ( WPAD_Probe(pad, &exp_type) != 0 )
		exp_type = WPAD_EXP_NONE;
	u32 wp = WPAD_ButtonsHeld(pad);
	if (wp & WPAD_BUTTON_RIGHT)
		J |= NDS_RIGHT;
	if (wp & WPAD_BUTTON_LEFT)
		J |= NDS_LEFT;
	if (wp & WPAD_BUTTON_UP)
		J |= NDS_UP;
	if (wp & WPAD_BUTTON_DOWN)
		J |= NDS_DOWN;
	if (exp_type == WPAD_EXP_CLASSIC)
	{
		if (wp & WPAD_CLASSIC_BUTTON_UP)
			J |= NDS_UP;
		if (wp & WPAD_CLASSIC_BUTTON_DOWN)
			J |= NDS_DOWN;
		if (wp & WPAD_CLASSIC_BUTTON_LEFT)
			J |= NDS_LEFT;
		if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
			J |= NDS_RIGHT;
	}
	if (jp & PAD_BUTTON_UP)
		J |= NDS_UP;
	if (jp & PAD_BUTTON_DOWN)
		J |= NDS_DOWN;
	if (jp & PAD_BUTTON_LEFT)
		J |= NDS_LEFT;
	if (jp & PAD_BUTTON_RIGHT)
		J |= NDS_RIGHT;
	return J;
}

u32 StandardClassic(unsigned short pad)
{
	u32 J = 0;
	u32 wp = WPAD_ButtonsHeld(pad);
	if (wp & WPAD_CLASSIC_BUTTON_A)
		J |= NDS_BUTTON_A;
	if (wp & WPAD_CLASSIC_BUTTON_B)
		J |= NDS_BUTTON_B;
	if (wp & WPAD_CLASSIC_BUTTON_X)
		J |= NDS_BUTTON_X;
	if (wp & WPAD_CLASSIC_BUTTON_Y)
		J |= NDS_BUTTON_Y;
	if (wp & WPAD_CLASSIC_BUTTON_UP)
		J |= NDS_UP;
	if (wp & WPAD_CLASSIC_BUTTON_RIGHT)
		J |= NDS_RIGHT;
	if (wp & WPAD_CLASSIC_BUTTON_DOWN)
		J |= NDS_DOWN;
	if (wp & WPAD_CLASSIC_BUTTON_LEFT)
		J |= NDS_LEFT;
	if (wp & WPAD_CLASSIC_BUTTON_FULL_L)
		J |= NDS_TRIGGER_L;
	if (wp & WPAD_CLASSIC_BUTTON_FULL_R)
		J |= NDS_TRIGGER_R;
	if (wp & WPAD_CLASSIC_BUTTON_PLUS)
		J |= NDS_START;
	if (wp & WPAD_CLASSIC_BUTTON_MINUS)
		J |= NDS_SELECT;
	if (wp & WPAD_BUTTON_A)
		J |= NDS_TAP;
	return J;
}

//u32 StandardGamecube(unsigned short pad)
//{
//	u32 J = 0;
//	u32 jp = PAD_ButtonsHeld(pad);
//	if (jp & PAD_BUTTON_A)
//		J |= NDS_BUTTON_A;
//	if (jp & PAD_BUTTON_B)
//		J |= NDS_BUTTON_B;
//	if (jp & PAD_BUTTON_X)
//		J |= NDS_BUTTON_X;
//	if (jp & PAD_BUTTON_Y)
//		J |= NDS_BUTTON_Y;
//	if (jp & PAD_BUTTON_UP)
//		J |= NDS_UP;
//	if (jp & PAD_BUTTON_RIGHT)
//		J |= NDS_RIGHT;
//	if (jp & PAD_BUTTON_DOWN)
//		J |= NDS_DOWN;
//	if (jp & PAD_BUTTON_LEFT)
//		J |= NDS_LEFT;
//	if (jp & PAD_TRIGGER_L)
//		J |= NDS_TRIGGER_L;
//	if (jp & PAD_TRIGGER_R)
//		J |= NDS_TRIGGER_R;
//	if (jp & PAD_BUTTON_START)
//		J |= NDS_START;
//	if (???)
//		J |= NDS_SELECT;
//	if (???)
//		J |= NDS_TAP;
//	return J;
//}

u32 StandardKeyboard(unsigned short pad)
{
	u32 J = 0;
	if (DownUsbKeys[KS_Z])
		J |= NDS_BUTTON_A;
	if (DownUsbKeys[KS_X])
		J |= NDS_BUTTON_B;
	if (DownUsbKeys[KS_C])
		J |= NDS_BUTTON_X;
	if (DownUsbKeys[KS_V])
		J |= NDS_BUTTON_Y;
	if (DownUsbKeys[KS_Up])
		J |= NDS_UP;
	if (DownUsbKeys[KS_Right])
		J |= NDS_RIGHT;
	if (DownUsbKeys[KS_Down])
		J |= NDS_DOWN;
	if (DownUsbKeys[KS_Left])
		J |= NDS_LEFT;
	if (DownUsbKeys[KS_Shift_L])
		J |= NDS_TRIGGER_L;
	if (DownUsbKeys[KS_Shift_R])
		J |= NDS_TRIGGER_R;
	if (DownUsbKeys[KS_Return])
		J |= NDS_START;
	if (DownUsbKeys[KS_space])
		J |= NDS_SELECT;
	if (DownUsbKeys[MOUSEL])
		J |= NDS_TAP;
	return J;
}

u32 DPadArrowKeys(unsigned short pad)
{
	u32 J = 0;
	if (DownUsbKeys[KS_Up])
		J |= NDS_UP;
	if (DownUsbKeys[KS_Down])
		J |= NDS_DOWN;
	if (DownUsbKeys[KS_Left])
		J |= NDS_LEFT;
	if (DownUsbKeys[KS_Right])
		J |= NDS_RIGHT;
	return J;
}

u32 DecodeKeyboard(unsigned short pad)
{
	u32 J = 0;
	for (u32 i = 0; i < MAXJP; ++i)
	{
		if (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]])
			J |= ndspadmap[i];
	}
	return J;
}

//u32 DecodeGamecube(unsigned short pad)
//{
//	u32 J = 0;
//	u32 jp = PAD_ButtonsHeld(pad);
//	for (u32 i = 0; i < MAXJP; ++i)
//	{
//		if (jp & btnmap[CTRLR_GCPAD][i])
//			J |= ndspadmap[i];
//	}
//	return J;
//}

u32 DecodeWiimote(unsigned short pad)
{
	u32 J = 0;
	WPADData * wp = WPAD_Data(pad);
	u32 wpad_btns_h = wp->btns_h;
	if(wp->exp.type == WPAD_EXP_NONE)
	{
		for (u32 i = 0; i < MAXJP; ++i)
		{
			if (wpad_btns_h & btnmap[CTRLR_WIIMOTE][i] )
				J |= ndspadmap[i];
		}
	}
	return J;
}

u32 DecodeClassic(unsigned short pad)
{
	u32 J = 0;
	WPADData * wp = WPAD_Data(pad);
	u32 wpad_btns_h = wp->btns_h;
	if(wp->exp.type == WPAD_EXP_CLASSIC){
		for (u32 i = 0; i < MAXJP; ++i){
			if (wpad_btns_h & btnmap[CTRLR_CLASSIC][i] )
				J |= ndspadmap[i];
		}
	}
	return J;
}

u32 DecodeNunchuk(unsigned short pad)
{
	u32 J = 0;
	u32 wpad_btns_h = userInput[pad].wpad->btns_h;
	if(userInput[pad].wpad->exp.type == WPAD_EXP_NUNCHUK){
		for (u32 i = 0; i < MAXJP; ++i){
			if (wpad_btns_h & btnmap[CTRLR_NUNCHUK][i] )
				J |= ndspadmap[i];
		}
	}
	return J;
}

/****************************************************************************
 * DecodeJoy
 *
 * Reads the STATE (not changes) from a controller and reports
 * this STATE (not changes)
 ****************************************************************************/
static u32 DecodeJoy(unsigned short pad)
{
	// the function result, J, is a combination of flags for all the NDS buttons that are down
	u32 J = StandardMovement(pad);

	// Report pressed buttons (gamepads)
	u32 pad_btns_h   = userInput[pad].pad.btns_h; // GCN

	u32 wpad_btns_h = userInput[pad].wpad->btns_h;
	int wpad_exp_type = userInput[pad].wpad->exp.type;

	if(wpad_exp_type == WPAD_EXP_NONE)
	{ // wiimote

		for (u32 i =0; i < MAXJP; ++i)
		{
			if ((pad_btns_h & btnmap[CTRLR_GCPAD][i]) // gamecube controller
					|| ( (wpad_btns_h & btnmap[CTRLR_WIIMOTE][i]) )
					|| ( (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) ) )
			J |= ndspadmap[i];
		}

	}
	else if(wpad_exp_type == WPAD_EXP_CLASSIC)
	{ // classic controller

		for (u32 i =0; i < MAXJP; ++i)
		{
			if ((pad_btns_h & btnmap[CTRLR_GCPAD][i]) // gamecube controller
					|| ( (wpad_btns_h & btnmap[CTRLR_CLASSIC][i]) )
					|| ( (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) ) )
			J |= ndspadmap[i];
		}

	}
	else if(wpad_exp_type == WPAD_EXP_NUNCHUK)
	{ // nunchuk + wiimote

		for (u32 i =0; i < MAXJP; ++i)
		{
			if ((pad_btns_h & btnmap[CTRLR_GCPAD][i]) // gamecube controller
					|| ( (wpad_btns_h & btnmap[CTRLR_NUNCHUK][i]) )
					|| ( (DownUsbKeys[btnmap[CTRLR_KEYBOARD][i]]) ) )
			J |= ndspadmap[i];
		}

	}
	else
	// Check out this trickery!
	// If all else fails, the result is the same
	{
		for (u32 i = 0; i < MAXJP; ++i)
		{
			if ((pad_btns_h & btnmap[CTRLR_GCPAD][i]))
				J |= ndspadmap[i];
		}
	}
	return J;
}

bool MenuRequested()
{
	if( (DownUsbKeys[KS_Escape]) 
		||
		(userInput[0].wpad->btns_h & WPAD_BUTTON_HOME) ||
		(userInput[0].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
		||
		(userInput[1].wpad->btns_h & WPAD_BUTTON_HOME) ||
		(userInput[1].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
		||
		(userInput[2].wpad->btns_h & WPAD_BUTTON_HOME) ||
		(userInput[2].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
		||
		(userInput[3].wpad->btns_h & WPAD_BUTTON_HOME) ||
		(userInput[3].wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME)
		)
	{
		return true;
	}
	return false;
}

u32 GetJoy(int pad)
{
	UpdatePads();
	// request to go back to menu
	if (MenuRequested())
	{
		ScreenshotRequested = 1;
		updateRumbleFrame();
		return 0;
	}
	u32 J = DecodeJoy(pad);
	// don't allow up+down or left+right
	if ((J & 48) == 48)
		J &= ~16;
	if ((J & 192) == 192)
		J &= ~128;
	updateRumbleFrame();
	return J;
}
